/*
 * 版权所有 (C) 2018 知启蒙(ZHIQIM) 保留所有权利。
 * 
 * 欢迎到知启蒙网站（https://www.zhiqim.com）购买正版软件，知启蒙还提供许多开源框架和软件。
 * 
 * 1、本软件产品所有源代码受《中华人民共和国著作权法》和其他有关法律、法规的保护，其所有知识产权归湖南知启蒙科技有限公司所有；
 * 2、禁止复制和修改。不得复制修改、翻译或改编本软件所有源代码，或者基于本软件产品创作衍生作品；
 * 3、禁止进行逆向工程。不得对本软件的源代码进行逆向工程、反编译或试图以其他方式发现软件的源代码；
 * 4、个别授权：如需进行商业性的销售、复制、分发，包括但不限于软件销售、预装、捆绑等，必须获得知启蒙的书面授权和许可；
 * 5、保留权利：本注释未明示授权的其他一切权利仍归知启蒙所有，任何人使用其他权利时必须获得知启蒙的书面同意。
 */
package net.redxyz.repost.service.dao;

import java.util.ArrayList;
import java.util.List;

import net.redxyz.repost.resource.model.AssRepostPlanChk;
import net.redxyz.repost.resource.model.SynItemOnsale;
import net.redxyz.repost.service.Main;
import net.redxyz.top.TaobaoService;
import net.redxyz.top.data.item.Item;
import net.redxyz.top.repost.dbo.AssRepostPlan;
import net.redxyz.top.repost.dbo.AssRepostPlanDetail;
import net.redxyz.top.repost.dbo.AssRepostSchedule;

import org.zhiqim.kernel.Global;
import org.zhiqim.kernel.logging.Log;
import org.zhiqim.kernel.util.Arrays;
import org.zhiqim.kernel.util.DateTimes;
import org.zhiqim.kernel.util.Validates;
import org.zhiqim.orm.ORM;
import org.zhiqim.orm.dbo.Selector;

/**
 * 均衡上架数据访问对象
 *
 * @version v1.0.0 @author zouzhigang 2014-3-21 新建与整理
 */
public class RepostDao
{
    public static int MAX_ITEMS = 20000; // 支持最高宝贝数
    public static int[] MINS = new int[] { // 分钟顺序
    /* 1 */30,
    /* 2 */15, 45,
    /* 4 */8, 22, 38, 52,
    /* 8 */4, 12, 18, 26, 34, 42, 48, 56,
    /* 16 */2, 6, 10, 14, 17, 20, 24, 28, 32, 36, 40, 44, 47, 50, 54, 58,
    /* o */1, 3, 5, 7, 9, 11, 13, 16, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 46, 49, 51, 53, 55, 57, 59, 0 };

    public static List<int[]> buildSequence(String planWeeks, String planHours)
    {
        int[] ws = Arrays.toIntArray(planWeeks.split(","));
        int[] hs = Arrays.toIntArray(planHours.split(","));
        return buildSequence(ws, hs);
    }

    public static String getDelistHour(String delistTime)
    {
        return delistTime.substring(11, 13);
    }

    public static int getDelistWeek(String delistTime)
    {
        return DateTimes.getDateTimeWeek7(delistTime);
    }

    public static String buildRepostTime(int[] p)
    {
        int planHour = p[1];
        int planMin = p[2];

        return buildRepostTime(planHour, planMin);
    }

    public static String buildRepostTimeByNum(int planHour, int num)
    {
        int v = num % 60;
        return buildRepostTime(planHour, MINS[v]);
    }

    public static String buildRepostTime(int planHour, int planMin)
    {
        String hour = String.valueOf(planHour);
        if (planHour < 10)
            hour = "0" + hour;

        String min = String.valueOf(planMin);
        if (planMin < 10)
            min = "0" + min;

        String planTime = hour + ":" + min + ":00";
        return planTime;
    }

    public static Item getRepostItem(int planWeek, String planTime, List<Item> itemList)
    {
        int seconds = 0;
        Item repostItem = itemList.get(0);
        for (int i = 0; i < itemList.size(); i++)
        {
            Item item = itemList.get(i);
            String delistTime = item.getDelistTime();
            String time = delistTime.substring(11, 19);

            int dweek = item.getDelistWeek();
            if (dweek < planWeek || (dweek == planWeek && time.compareTo(planTime) < 0))
                dweek += 7;// 如果下架时间周期在调整时间之前，则+7

            int nseconds = compareSecond(time, planTime);
            int distance = 60 * 60 * 24 * (dweek - planWeek) + nseconds;

            if (distance > seconds)
            {
                seconds = distance;
                repostItem = item;
            }
        }

        itemList.remove(repostItem);

        return repostItem;
    }

    /************************************************/
    // 检查均衡上架计划
    /************************************************/

    public static void doChkRepostPlan(Log log, String nick, String sessionId, String datetime, List<AssRepostPlan> planList)
        throws Exception
    {
        // 清理非法的数据
        deleteInvoidDetail(planList, nick);

        List<SynItemOnsale> itemList = doSyncUserItem(log, nick, sessionId, datetime);
        if (itemList == null || itemList.isEmpty())
        {
            log.info("宝贝同步任务[" + nick + "][用户同步失败]");
            return;
        }

        // 均衡上架检查
        doRepostCheck(nick, itemList);
    }

    private static List<int[]> buildSequence(int[] weeks, int[] hours)
    {
        int[] hour24 = new int[] { 20, 16, 11, 21, 15, 10, 22, 17,// 全天黄金
            12, 19, 18, 13, 14, 9,// 全天9-23
            23, 8, 0, 1, 2, 3, 7, 4, 5, 6 // 剩余
        };

        // 过滤掉没有
        for (int i = 0; i < hour24.length; i++)
        {
            boolean isExists = false;
            for (int hh : hours)
            {
                if (hour24[i] == hh)
                {
                    isExists = true;
                    break;
                }
            }

            if (!isExists)
                hour24[i] = -1;
        }

        int maxNum = (MAX_ITEMS - 1) / (weeks.length * hours.length * 60) + 1;
        List<int[]> pos = new ArrayList<int[]>();

        for (int n = 1; n <= maxNum; n++)
        {
            for (int m : MINS)
            {
                for (int h : hour24)
                {
                    if (h == -1)
                        continue;

                    for (int w : weeks)
                    {
                        int[] num = new int[] { w, h, m, n };
                        pos.add(num);
                        if (pos.size() == MAX_ITEMS)
                            return pos;

                    }
                }
            }
        }

        return pos;
    }

    /** 求两个时间的差错 */
    private static int compareSecond(String dtime, String ptime)
    {
        int dhour = Integer.parseInt(dtime.substring(0, 2));
        int dmin = Integer.parseInt(dtime.substring(3, 5));
        int dsec = Integer.parseInt(dtime.substring(3, 5));

        int phour = Integer.parseInt(ptime.substring(0, 2));
        int pmin = Integer.parseInt(ptime.substring(3, 5));
        int psec = Integer.parseInt(ptime.substring(3, 5));

        return (dhour - phour) * 3600 + (dmin - pmin) * 60 + (dsec - psec);
    }

    /**
     * 清理计划已删除，详情未删除的数据
     * @param planList
     * @param nick
     * @param userDomain
     * @param userDb
     * @throws Exception
     */
    private static void deleteInvoidDetail(List<AssRepostPlan> planList, String nick) throws Exception
    {
        String[] planIds = new String[planList.size()];
        for (int i = 0; i < planList.size(); i++)
            planIds[i] = planList.get(i).getPlanId();

        Selector selector = new Selector();
        selector.addReplace("d", "001");
        selector.addMaybe("nick", nick);
        selector.addMaybeNotIn("planId", planIds);
        ORM.table().delete(AssRepostPlanDetail.class, selector);
    }

    private static List<SynItemOnsale> doSyncUserItem(Log log, String nick, String sessionId, String currentTime)
    {
        try
        {
            List<Item> onsaleItemList = TaobaoService.getItemService().getOnsaleItemListAll(nick, sessionId);
            List<SynItemOnsale> itemList = new ArrayList<SynItemOnsale>();

            // 查询指定上下架计划宝贝
            List<AssRepostSchedule> repostItemList = ORM.table().list(AssRepostSchedule.class, new Selector("nick", nick));

            for (Item tItem : onsaleItemList)
            {
                long numIid = tItem.getNumIid();
                // 宝贝编号为0或下架时间为空，认为是淘宝接口来的错误数据，过滤
                if (numIid == 0 || Validates.isEmpty(tItem.getDelistTime()))
                    continue;

                // 加入指定上下架计划的宝贝要过滤
                if (isExists(repostItemList, numIid))
                    continue;

                String delistTime = tItem.getDelistTime();
                if (tItem.getDelistTime().compareTo(currentTime) <= 0)
                {// 如果数据库时间小于当前时间，加7天吧。
                    delistTime = DateTimes.getNextDateTimeStringByHour(delistTime, 7 * 24);
                }

                SynItemOnsale item = new SynItemOnsale();
                item.setNick(nick);
                item.setDelistTime(delistTime);
                item.setHasShowcase("true".equals(tItem.getHasShowcase()) ? 1 : 0);
                item.setModified(tItem.getModified());
                item.setNum(tItem.getNum());
                item.setNumIid(numIid);
                item.setPicUrl(tItem.getPicUrl());
                item.setPrice(tItem.getPrice());
                item.setSellerCids(tItem.getSellerCids());
                item.setCid(tItem.getCid());
                item.setTitle(tItem.getTitle());

                itemList.add(item);
            }

            return itemList;
        }
        catch (Exception e)
        {
            log.info("宝贝同步任务[" + nick + "][用户同步异常]", e);
            return null;
        }
    }

    private static void doRepostCheck(String nick, List<SynItemOnsale> itemList) throws Exception
    {
        AssRepostPlanChk rcDto = new AssRepostPlanChk();
        rcDto.setNick(nick);
        rcDto.setUserDb(0);
        rcDto.setUserDomain("001");
        rcDto.setItemList(itemList);
        Global.getService(Main.class).postRequest(rcDto);
    }

    /**
     * 判断是否加入指定上下架计划
     *
     * @param repostList
     * @param numIid
     * @return
     */
    private static boolean isExists(List<AssRepostSchedule> repostList, long numIid)
    {
        for (AssRepostSchedule item : repostList)
        {
            if (item.getNumIid() == numIid)
                return true;
        }

        return false;
    }
}
